package com.danieltoms.gcSync.google.feed;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;

import javax.microedition.io.HttpConnection;
import javax.microedition.io.HttpsConnection;

import com.danieltoms.gcSync.GcSyncStore;
import com.danieltoms.gcSync.google.GoogleLoginException;
import com.danieltoms.io.HttpConnectionHelper;

public class GoogleClientLoginFeed
{

	private static final String ERROR_HEADER = "Error=";
	private static final String AUTH_HEADER = "Auth=";
	private static final String PASSWD = "Passwd";
	private static final String EMAIL = "Email";
	private static final String SOURCE = "source";
	private static final String CONTACT_SERVICE = "cp";
	private static final String SERVICE = "service";
	private static final String HOSTED_OR_GOOGLE = "GOOGLE";
	private static final String ACCOUNT_TYPE = "accountType";

	static class PrepareRequest implements HttpConnectionHelper.Callback
	{

		private static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
		private static final String CONTENT_TYPE = "Content-Type";
		private static final String EN_US = "en-US";
		private static final String ACCEPT_LANGUAGE = "Accept_Language";
		private static final String MIDP1 = "Profile/MIDP-1.0 Configuration/CLDC-1.0";
		private static final String USER_AGENT = "User-Agent";
		public static final Hashtable m_args = new Hashtable();

		public void prepareRequest(String originalURL, HttpConnection conn) throws IOException
		{

			conn.setRequestMethod(HttpsConnection.POST);
			conn.setRequestProperty(USER_AGENT, MIDP1);
			conn.setRequestProperty(ACCEPT_LANGUAGE, EN_US);
			// Content-Type is must to pass parameters in POST Request
			conn.setRequestProperty(CONTENT_TYPE, APPLICATION_X_WWW_FORM_URLENCODED);

		}

		public void addPostParameter(String name, String value)
		{
			m_args.put(name, value);
		}

		public void preparePost(HttpConnection c) throws IOException
		{
			StringBuffer postOutput = new StringBuffer();

			// apparently for google ORDER IS IMPORTANT, or you'll get a 403 :(
			postOutput.append(ACCOUNT_TYPE);
			postOutput.append('=');
			postOutput.append(HOSTED_OR_GOOGLE);
			postOutput.append('&');
			postOutput.append(EMAIL);
			postOutput.append('=');
			postOutput.append(m_args.get(EMAIL));
			postOutput.append('&');
			postOutput.append(PASSWD);
			postOutput.append('=');
			postOutput.append(m_args.get(PASSWD));
			postOutput.append('&');
			postOutput.append(SERVICE);
			postOutput.append('=');
			postOutput.append(CONTACT_SERVICE);

			OutputStream os = c.openOutputStream();
			os.write(postOutput.toString().getBytes());
			os.flush();

		}

	}

	public static final String GOOGLE_CLIENT_LOGIN_URL = "https://www.google.com/accounts/ClientLogin";
	private static final PrepareRequest m_prepareRequest = new PrepareRequest();

	private String m_errorCode = null;

	public boolean authenticate(String email, String password) throws GoogleLoginException
	{
		boolean authenticated = false;
		System.out.println("Authenticate email: " + email + " password: " + password);

		HttpsConnection c = null;
		InputStream is = null;
		int rc = -1;

		try
		{
			m_prepareRequest.addPostParameter(EMAIL, email);
			m_prepareRequest.addPostParameter(PASSWD, password);

			c = (HttpsConnection) HttpConnectionHelper.connectSecure(GOOGLE_CLIENT_LOGIN_URL, m_prepareRequest);

			rc = c.getResponseCode();
			is = c.openDataInputStream();
			String body = readBody(c, is);
			System.out.println(body);
			if (rc == HttpConnection.HTTP_OK)
			{
				String auth = parseHeader(body, AUTH_HEADER);
				GcSyncStore.instance().storeAuthToken(auth);
				authenticated = true;

			} // end if
			else if (rc == HttpConnection.HTTP_FORBIDDEN)
			{
				/*
				 * Url=http://www.google.com/login/captcha Error=CaptchaRequired
				 * CaptchaToken=DQAAAGgA...dkI1LK9
				 * CaptchaUrl=Captcha?ctoken=HiteT4b0Bk5Xg18_AcVoP6-yFkHPibe7O9EqxeiI7lUSN
				 */

				m_errorCode = parseHeader(body, ERROR_HEADER);

			}

			c.close();
		}
		catch (IOException ex)
		{
			m_errorCode = "IOException";

			throw new GoogleLoginException(m_errorCode);
		}

		return authenticated;

	}

	private String parseHeader(String body, String header)
	{
		int start = body.indexOf(header);
		if (start != -1)
		{
			start += header.length();
			int end = body.indexOf('\n', start);
			header = body.substring(start, end);
		}

		return header;
	}

	private String readBody(HttpsConnection c, InputStream is) throws IOException
	{
		// this code came from the BlackBerry HttpConnection sample I believe
		// Get the length and process the data
		int len = (int) c.getLength();

		// read all the data
		int actual = 0;
		int bytesread = 0;
		byte[] data = new byte[len];
		while ((bytesread != len) && (actual != -1))
		{
			actual = is.read(data, bytesread, len - bytesread);
			bytesread += actual;
		}

		return new String(data);

	}

	public String getErrorCode()
	{
		return m_errorCode;
	}

}
